﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Printing;
using System.IO;

namespace DCSoft.TemperatureChart
{
    /// <summary>
    /// 体温单控件
    /// </summary>
    /// <remarks></remarks>
    [ToolboxItem(true)]
    [System.Runtime.InteropServices.ComVisible(false)]
    public partial class TemperatureControl : UserControl
    {
        /// <summary>
        /// 初始化对象
        /// </summary>
        public TemperatureControl()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (DesignMode == false)
            {
                UpdateState();
                UpdateViewSize();
            }
        }

        private TemperatureDocumentOptions _DocumentOptions = null;
        /// <summary>
        /// 文档选项
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
        public TemperatureDocumentOptions DocumentOptions
        {
            get
            {
                if (_DocumentOptions == null)
                {
                    _DocumentOptions = new TemperatureDocumentOptions();
                    _DocumentOptions.InitDefaultSettings();
                }
                return _DocumentOptions; 
            }
            set 
            {
                _DocumentOptions = value; 
            }
        }

        private TemperatureDocument _Document = null;
        /// <summary>
        /// 体温单文档对象
        /// </summary>
        [Browsable( false )]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
        public TemperatureDocument Document
        {
            get
            {
                if (_Document == null)
                {
                    _Document = new TemperatureDocument();
                    _Document.Options = DocumentOptions;
                }
                return _Document; 
            }
            set
            {
                _Document = value;
                if (_Document != null)
                {
                    _Document.Options = DocumentOptions;
                }
                if (IsHandleCreated)
                {
                    UpdateViewSize();
                }
            }
        }

        private TemperatureDocumentRender _DocumentRender = new TemperatureDocumentRender();
        /// <summary>
        /// 文档内容绘制器
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public TemperatureDocumentRender DocumentRender
        {
            get
            {
                return _DocumentRender; 
            }
            set
            {
                _DocumentRender = value; 
            }
        }

        private PageSettings _PageSettings = new PageSettings();
        /// <summary>
        /// 页面设置
        /// </summary>
        [Browsable( false )]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public PageSettings PageSettings
        {
            get
            {
                return _PageSettings; 
            }
            set
            {
                _PageSettings = value;
                if (DesignMode == false)
                {
                    UpdateViewSize();
                }
            }
        }

        private Color _pageBackColor = Color.White;
        /// <summary>
        /// 页面背景色
        /// </summary>
        [DefaultValue(typeof(Color) , "White")]
        [Category("Appearance")]
        public Color PageBackColor
        {
            get
            {
                return _pageBackColor; 
            }
            set
            {
                _pageBackColor = value; 
            }
        }

        /// <summary>
        /// 更新文档视图绘制体温单
        /// </summary>
        public void RefreshView()
        {
            UpdateState();
            UpdateViewSize();
            pnlView.Invalidate();//使控件的整个图面无效并重绘控件
        }

        /// <summary>
        /// 更新控件状态
        /// </summary>
        public void UpdateState()
        {
            if (Document != null)
            {
                Document.UpdateState();
                DateTime max = TemperatureDocument.NullDate;
                DateTime min = TemperatureDocument.NullDate;
                Document.UpdateNumOfPage( out max , out min );
                cboPageIndex.Items.Clear();
                for (int iCount = 0; iCount < Document.NumOfPages; iCount ++ )
                {
                    cboPageIndex.Items.Add( iCount + 1 );
                }
                if (cboPageIndex.Items.Count > 0)
                {
                    cboPageIndex.SelectedIndex = 0;
                }
            }
        }

        private Rectangle _PageBounds = Rectangle.Empty;
        private Rectangle _DocumentBounds = Rectangle.Empty;
        private void UpdateViewSize()
        {
            if (IsHandleCreated && Document != null && DesignMode == false )
            {
                using (Graphics g = pnlView.CreateGraphics())
                {
                    // 计算页面框架视图边界
                    _PageBounds = new Rectangle( 10, 10, (int)(g.DpiX * PageSettings.Bounds.Width / 100f), (int)(g.DpiY * PageSettings.Bounds.Height / 100f) );
                    if (_PageBounds.Width + 20 < ClientSize.Width)
                    {
                        _PageBounds.X = 10 + (ClientSize.Width - _PageBounds.Width) / 2;//横坐标居中显示
                    }
                    // 计算体温单文档视图边界
                    _DocumentBounds.X = _PageBounds.X + (int)(PageSettings.Margins.Left * g.DpiX / 100f);
                    _DocumentBounds.Y = _PageBounds.Y + (int)(PageSettings.Margins.Top * g.DpiY / 100f);
                    _DocumentBounds.Width = _PageBounds.Right - (int)(PageSettings.Margins.Right * g.DpiX / 100f) - _DocumentBounds.Left;
                    _DocumentBounds.Height = _PageBounds.Bottom - (int)(PageSettings.Margins.Bottom * g.DpiY / 100f) - _DocumentBounds.Top;

                    Size viewSize = new Size( _PageBounds.Left + 10 , _PageBounds.Bottom + 10 );
                    
                    if (pnlView.AutoScrollMinSize != viewSize)
                    {
                        pnlView.AutoScrollMinSize = viewSize;
                    }
                }
            }
        }


        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (DesignMode == false)
            {
                pnlView.Invalidate();
                UpdateViewSize();
            }
        }
        /// <summary>
        /// 重新绘制控件事件(滚动鼠标时会调用该事件重新绘制体温单)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pnlView_Paint(object sender, PaintEventArgs e)
        {
            if (Document == null)
            {
                return;
            }
            // 绘制页面边框
            Rectangle pb = _PageBounds;
            pb.Offset(pnlView.AutoScrollPosition.X, pnlView.AutoScrollPosition.Y);//设置矩形的位置
            Rectangle pb2 = Rectangle.Intersect(pb, e.ClipRectangle);
            if (pb2.IsEmpty)
            {
                return;
            }
            using (SolidBrush b = new SolidBrush(PageBackColor))
            {
                e.Graphics.FillRectangle(b, pb2);
            }
            e.Graphics.DrawRectangle(Pens.Black, pb);
            // 绘制文档
            Rectangle db = _DocumentBounds;
            db.Offset(pnlView.AutoScrollPosition.X, pnlView.AutoScrollPosition.Y);
            if (e.ClipRectangle.IntersectsWith(db))//判断新的体温单文档对象是否在页面对象的边界中
            {
                TemperatureDocumentOptions options = DocumentOptions;
                options.FontName = Font.Name;
                options.FontSize = Font.Size;
                Document.UpdateState();
                Document.PageIndex = cboPageIndex.SelectedIndex;
                options.Left = db.Left-30;
                options.Top = db.Top;
                options.Width = db.Width+60;
                options.Height = db.Height;
                DocumentRender.Draw(e.Graphics, Document);
            }
        }

        private void cboPageIndex_SelectedIndexChanged(object sender, EventArgs e)
        {
            pnlView.Invalidate();
        }
        /// <summary>
        /// 打印当前页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrintCurrentPage_Click(object sender, EventArgs e)
        {
            PrintDocument(true);
        }
        /// <summary>
        /// 打印所有
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrintAll_Click(object sender, EventArgs e)
        {
            PrintDocument(false);
        }
        /// <summary>
        /// 打印体温单
        /// </summary>
        /// <param name="currentPage"></param>
        private void PrintDocument( bool currentPage )
        {
            using (PrintDialog dlg = new PrintDialog())
            {
                dlg.AllowCurrentPage = false;
                dlg.AllowSelection = false;
                dlg.AllowSomePages = false;
                if (dlg.ShowDialog(this) == DialogResult.OK)//确定打印
                {
                    using (TemperaturePrintDocument tpd = new TemperaturePrintDocument(Document ,DocumentRender))
                    {
                        if (currentPage)
                        {
                            // 指定当前页
                            tpd.SpecifyPageIndex = cboPageIndex.SelectedIndex;
                        }
                        tpd.PrinterSettings = dlg.PrinterSettings;
                        tpd.DefaultPageSettings = PageSettings;
                        tpd.Print();
                    }
                }
            }
        }

        /// <summary>
        /// 从文件流中加载文档
        /// </summary>
        /// <param name="stream">文件流对象</param>
        public void LoadDocument(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            TemperatureDocument doc = new TemperatureDocument();
            if( doc.Load(stream) )
            {
                Document = doc;
                if (IsHandleCreated)
                {
                    UpdateState();
                    pnlView.Invalidate();
                }
            }
        }

        public void SaveDocument(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (Document != null)
            {
                Document.Save(stream);
            }
        }
    }
}
